import 'dart:async';

import '../flutter_lui.dart';

/// 模型基类 \
/// 需要实现解析方法`parse` 解析方法接收一个Map，子类子类中的属性可以通过map赋值 \
/// 需要实现toMap方法，将对象转换为Map \
/// 需要实现复制方法`clone` 用于复制和自身内容一样的新对象
abstract class LStoreModel {
  LStoreModel parse(Map data);
  LStoreModel clone();
  Map<String, dynamic> toMap();
  bool isEqual(LStoreModel? d) {
    return toString() == d?.toString();
  }

  @override
  String toString() {
    return toMap().toString();
  }
}

/// 数据结果集基类 \
/// 定义了基本的请求状态属性、错误信息和对比方法 \
/// 需要实现复制方法`clone` 用于复制和自身内容一样的新对象，
/// 在正式使用数据的时候返回复制的新对象，防止直接修改仓库里的数据 \
/// 需要实现toString方法，用于对比两个对象是否相同
abstract class LStoreResult {
  bool fetching = false;
  bool loaded = false;
  dynamic error;

  LStoreResult clone();

  bool isEqual(LStoreResult? d) {
    return toString() == d?.toString();
  }
}

/// 列表类型的数据结果集
/// 定义了列表数据的类型
class LStoreResultList<T extends LStoreModel> extends LStoreResult {
  List<T> results = [];
  @override
  String toString() {
    return {
      'fetching': fetching,
      'loaded': loaded,
      'error': error,
      'results': results.map((e) => e.toString()).toList(),
    }.toString();
  }

  @override
  LStoreResultList<T> clone() {
    LStoreResultList<T> n = LStoreResultList<T>();
    n.fetching = fetching;
    n.loaded = loaded;
    n.results = (results).map((e) => e.clone() as T).toList();
    n.error = error;
    return n;
  }
}

/// 分页类型的数据结果集
class LStoreResultPaginate<T extends LStoreModel> extends LStoreResult {
  int page = 1;
  int pageSize = 0;
  int total = 0;
  int totalPage = 0;
  List<T> results = [];
  @override
  String toString() {
    return {
      'fetching': fetching,
      'loaded': loaded,
      'error': error,
      'page': page,
      'pageSize': pageSize,
      'total': total,
      'totalPage': totalPage,
      'results': results.map((e) => e.toString()).toList(),
    }.toString();
  }

  @override
  LStoreResultPaginate<T> clone() {
    LStoreResultPaginate<T> n = LStoreResultPaginate<T>();
    n.fetching = fetching;
    n.loaded = loaded;
    n.error = error;
    n.page = page;
    n.pageSize = pageSize;
    n.total = total;
    n.totalPage = totalPage;
    n.results = (results).map((e) => e.clone() as T).toList();
    return n;
  }
}

/// 详情类型的数据结果集
class LStoreResultDetail<T extends LStoreModel> extends LStoreResult {
  T? result;
  @override
  String toString() {
    return {
      'fetching': fetching,
      'loaded': loaded,
      'error': error,
      'result': result?.toString(),
    }.toString();
  }

  @override
  LStoreResultDetail<T> clone() {
    LStoreResultDetail<T> n = LStoreResultDetail<T>();
    n.fetching = fetching;
    n.loaded = loaded;
    n.error = error;
    n.result = result?.clone() as T?;
    return n;
  }
}

class Action {
  final dynamic type;
  Action(this.type);
}

/// 中间件处理函数 \
/// 返回true则继续执行下一个中间件 \
/// 返回false则终止后续中间件执行 \
/// 如果是异步函数则返回Future<bool>
typedef MiddlewareHandler<State> = dynamic Function(
    LStore<State> store, dynamic action);

/// 使用方式
///
/// 一 定义模型
///
/// ```
/// class Income extends LStoreModel {
///  String? name;
///
///  @override
///  Income parse(dynamic data) {
///    name = data?['name'];
///   return this;
///  }
///
///  @override
/// Map<String, dynamic> toMap() {
///   return {
///     'name': name,
///   };
///  }
///
///  @override
///  LStoreModel clone() {
///    return Income().parse(toMap());
///  }
/// }
/// ```
/// 二  定义派发事件
/// ```
/// enum ActionType {
///  incomeListRequest,
///  incomeListSuccess,
///  incomeListFailure,
///  userNmaeUpdate
/// }
/// ```
/// 三 定义State
/// ```
/// class AppState {
///   LStoreResultList<Income> incomeList = LStoreResultList();
///   String userName = 'test';
///   AppState clone() {
///     var newState = AppState();
///     newState.incomeList = incomeList.clone();
///     newState.userName = userName;
///     return newState;
///   }
/// }
///
/// ```
/// 四 定义数据处理
///
/// 以获取income列表为例：
/// ```
///  1, 定义请求action 包含请求参数
/// class IncomeListRequestAction extends Action {
///   final bool forceRefresh;
///   IncomeListRequestAction({this.forceRefresh = false})
///       : super(ActionType.incomeListRequest);
/// }
/// 2，定义请求成功action 包含结果
/// class IncomeListSuccessAction extends Action {
///   List<Income> results;
///   IncomeListSuccessAction(this.results) : super(ActionType.incomeListSuccess);
/// }
/// 3,定义请求失败action 包含错误信息
/// class IncomeListFailureAction extends Action {
///   final dynamic error;
///   IncomeListFailureAction(this.error) : super(ActionType.incomeListFailure);
/// }
/// 4,定义请求reducer
/// AppState incomeListRequest(AppState state, IncomeListRequestAction action) {
///   var newState = state.clone();
///   var incomeList = newState.incomeList;
///   incomeList.fetching = true;
///   return newState;
/// }
/// 5,定义请求成功reducer
/// AppState incomeListSuccess(AppState state, IncomeListSuccessAction action) {
///   var newState = state.clone();
///   var incomeList = newState.incomeList;
///   incomeList.fetching = false;
///   incomeList.loaded = true;
///   incomeList.results = action.results;
///   return newState;
/// }
/// 6,定义请求失败reducer
/// AppState incomeListFailure(AppState state, IncomeListFailureAction action) {
///   var newState = state.clone();
///   var incomeList = newState.incomeList;
///   incomeList.fetching = false;
///   incomeList.loaded = true;
///   incomeList.error = action.error;
///   return newState;
/// }
///
/// 7，定义请求接口数据解析
/// incomeListHook(LStore<AppState> store, dynamic action) async {
///   if (action.type == ActionType.incomeListRequest) {
///     var iaction = action as IncomeListRequestAction;
///     List<Income> list = [];
///     for (var i = 0; i < 10; i++) {
///       list.add(Income()
///           .parse({'name': 'force=> ${iaction.forceRefresh} income name: $i'}));
///     }
///     store.dispatch(IncomeListSuccessAction(list));
///     return false;
///   }
///   return true;
/// }
///
///
/// ```
/// 不需要请求的数据举例：
///
/// ```
/// 1,定义更新action 包含参数
/// class UserNameUpdateAction extends Action {
///   final String userName;
///   UserNameUpdateAction(this.userName) : super(ActionType.userNmaeUpdate);
/// }
/// 2，定义更新reducer
/// AppState userNameUpdate(AppState state, UserNameUpdateAction action) {
///   var newState = state.clone();
///   newState.userName = '${newState.userName}+1';
///   return newState;
/// }
/// ```
///
/// 使用：
/// ```
/// 1,实例化store
/// LStore<AppState> store = LStore<AppState>(
///   initialState: AppState(),
///   reducers: {
///     ActionType.incomeListRequest: incomeListRequest,
///     ActionType.incomeListSuccess: incomeListSuccess,
///     ActionType.incomeListFailure: incomeListFailure,
///     ActionType.userNmaeUpdate: userNameUpdate
///   },
///   middleware: [
///     storeLogMiddleware,
///     incomeListHook,
///   ],
/// );
///
/// 2，派发事件
/// store.dispatch(IncomeListRequestAction());
///
/// 3，使用mixin在页面上监听数据变化
///  a, 定义一个 mixin,在各个需要数据的页面加上
/// mixin LStoreMixin<T extends StatefulWidget> on State<T> {
///   late StreamSubscription<AppState> stream;
///   @override
///   @mustCallSuper
///   void initState() {
///     super.initState();
///     stream = app.store.change.listen(connect);
///     connect(app.store.state);
///   }
///
///   void connect(AppState state) {}
///
///   @override
///   @mustCallSuper
///   void dispose() {
///     stream.cancel();
///     super.dispose();
///   }
/// }
///
///
/// b,在页面内使用
/// class _MyHomePageState extends State<MyHomePage> with LStoreMixin {
///    @override
///    void connect(AppState state) {
///      print('state change ${state.incomeList}');
///    }
/// }
/// ```
///
///

/// 总控制类
class LStore<State> {
  /// 状态仓库
  late State _state;

  /// 状态处理函数Map
  /// 以type为key ，状态处理函数为值
  ///  Map<ActionType, subReducer>
  late final Map _reducers;

  /// 中间件处理函数
  late final List<MiddlewareHandler<State>> _middleware;

  /// 数据变化通知流
  final StreamController<State> _changeController =
      StreamController.broadcast();

  /// 事件派发队列
  final List<dynamic> dispatchQueue = [];

  /// 是否正在执行队列
  bool _dispatchQueueRunning = false;

  /// 构造函数
  LStore(
      {required initialState,
      required Map reducers,
      List<MiddlewareHandler<State>> middleware = const []}) {
    _state = initialState;
    _middleware = middleware;
    _reducers = reducers;
  }

  /// 获取状态
  State get state => _state;

  /// 状态变化通知句柄
  Stream<State> get change => _changeController.stream;

  /// 事件派发
  dispatch(dynamic action) {
    dispatchQueue.add(action);
    runQueue();
  }

  State mainReducer(State state, dynamic action) {
    var fn = _reducers[action.type];
    if (fn != null) {
      return fn(state, action);
    }
    return state;
  }

  /// 执行队列
  runQueue() async {
    // 如果队列正在执行中，则暂不执行
    if (_dispatchQueueRunning) return;
    // 如果队列为空，则结束本次执行
    if (dispatchQueue.isEmpty) {
      _dispatchQueueRunning = false;
      return;
    }
    // 设置队列开始执行
    _dispatchQueueRunning = true;
    // 获取队列中的第一个事件
    var action = dispatchQueue.removeAt(0);
    // 执行事件
    _state = mainReducer(state, action);
    // 把最新的数据发送到通知流中
    _changeController.add(_state);
    // 执行中间件
    for (var i = 0; i < _middleware.length; i++) {
      var res = _middleware[i](this, action);
      if (res == true) {
        continue;
      } else if (res is Future) {
        res = await res;
        if (res == true) {
          continue;
        }
      } else {
        break;
      }
    }
    // 本次队列执行结束
    _dispatchQueueRunning = false;
    // 开始执行下一次队列
    runQueue();
  }
}

/// 事件派发日志中间件
storeLogMiddleware(dynamic store, dynamic action) {
  LColorPrint.colour([
    '💙store',
    '->',
    'action: ',
    action.type
  ], [
    LColorPrintColor.colorYellow,
    LColorPrintColor.colorMagenta,
    LColorPrintColor.colorGreen,
    LColorPrintColor.colorCyan
  ]);
  return true;
}
